package com.iot08.common.config.redis;

import com.iot08.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Redis 缓存
 * @version 1.0
 * @Description:
 * @author: Weichao
 * @time: 2020/9/7 11:27
 */
@Slf4j
@Component
public class RedisService {

    @Value("${redis.pool.host}")
    private String server;
    @Value("${redis.pool.port}")
    private Integer port;
    @Value("${redis.pool.database}")
    private Integer database;
    @Value("${redis.pool.password}")
    private String password;
    @Value("${redis.pool.maxTotal}")
    private Integer poolMaxTotal;
    @Value("${redis.pool.maxIdle}")
    private Integer poolMaxIdle;
    @Value("${redis.pool.minIdle}")
    private Integer poolMinIdle;
    @Value("${redis.pool.maxWaitMillis}")
    private Long poolMaxWaitMillis;
    @Value("${redis.pool.testOnBorrow}")
    private Boolean poolTestOnBorrow;
    @Value("${redis.pool.testOnReturn}")
    private Boolean poolTestOnReturn;

    private static JedisPool jedisPool;

    @PostConstruct
    private void init() {
        log.info("初始化 redis 单实例配置数据: server={} port={} database={}", server, port, database);
        JedisPoolConfig config = new JedisPoolConfig();
        //最大连接数, 默认8个
        config.setMaxTotal(poolMaxTotal);
        // 最大空闲连接数, 默认8个
        config.setMaxIdle(poolMaxIdle);
        // 最小空闲连接数, 默认8个
        config.setMinIdle(poolMinIdle);
        // 当池内没有对象返回时，最大的等待时间
        config.setMaxWaitMillis(poolMaxWaitMillis);
        // 当调用borrow Object方\法时，是否进行有效性检查
        config.setTestOnBorrow(poolTestOnBorrow);
        // 当调用return Object方法时，是否进行有效性检查
        config.setTestOnReturn(poolTestOnReturn);
        //配置 , host , port , 连接超时时间 ,密码 , DB名字
        if (StringUtil.isBlank(password)) {
            password = null;
        }
        jedisPool = new JedisPool(config, server, port, 10000, password, database);
//        log.info("jedisPool={} ", jedisPool);
    }


    /**
     * @time: 2020/9/25 14:13
     * @author: Weichao
     * @version 1.0
     */
    private Jedis getRedisClient() {
        try {
            return jedisPool.getResource();
        } catch (Exception e) {
            log.error("getRedisClient error", e);
        }
        return null;
    }

    /**
     * @param key
     * @param value
     * @time: 2020/11/2 16:30
     * @author: Weichao
     * @version 1.0
     */
    public String set(String key, String value) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.set(key, value);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param second
     * @param value
     * @time: 2020/11/4 11:29
     * @author: Weichao
     * @version 1.0
     */
    public String setex(String key, int second, String value) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.setex(key, second, value);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @time: 2020/11/2 16:31
     * @author: Weichao
     * @version 1.0
     */
    public String get(String key) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.get(key);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param field
     * @time: 2020/10/17 10:17
     * @author: Weichao
     * @version 1.0
     */
    public String hget(String key, String field) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.hget(key, field);
            } finally {
                jedis.close();
            }
        }
        return null;
    }


    /**
     * 获取多个 hex Map 的值
     * @param key
     * @param fields
     * @time: 2021/08/25 15:17
     * @author: Weichao
     * @version 1.0
     */
    public List<String> hmget(String key, String... fields) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.hmget(key, fields);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param field
     * @param value
     * @time: 2020/9/25 14:19
     * @author: Weichao
     * @version 1.0
     */
    public Long hset(String key, String field, String value) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.hset(key, field, value);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param field
     * @time: 2020/9/25 14:20
     * @author: Weichao
     * @version 1.0
     */
    public Long hdel(String key, String field) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.hdel(key, field);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @time: 2020/10/20 11:17
     * @author: Weichao
     * @version 1.0
     */
    public Long del(String key) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.del(key);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param keys
     * @time: 2020/10/20 11:17
     * @author: WeiChao
     * @version 1.0
     */
    public Long mdel(String... keys) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.del(keys);
            } finally {
                jedis.close();
            }
        }
        return null;
    }


    /**
     * @param key
     * @time: 2021/1/15 11:09
     * @author: Weichao
     * @version 1.0
     */
    public Map<String, String> hgetAll(String key) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.hgetAll(key);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param value
     * @time: 2021/1/15 11:23
     * @author: Weichao
     * @version 1.0
     */
    public void hmset(String key, Map<String, String> value) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                jedis.hmset(key, value);
            } finally {
                jedis.close();
            }
        }
    }

    /**
     * @param key
     * @time: 2021/2/26 9:10
     * @author: Weichao
     * @version 1.0
     */
    public Set<String> keys(String key) {
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.keys(key);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * @description key的内容自增
     * @author cwj
     * @param [key, delta]
     * @return java.lang.Long
     * @date @time 2024/11/19 17:37
     **/
    public Long incr(String key, long delta) {
        Jedis jedis = getRedisClient();
        if (delta < 0L) {
            throw new RuntimeException("递增因子必须大于0");
        } else {
            if (jedis != null){
                try {
                    return jedis.incrBy(key,delta);
                } finally {
                    jedis.close();
                }
            }
        }
        return null;
    }

    /**
     * @description 检查key是否存在或过期
     * @author cwj
     * @param [key]
     * @return boolean
     * @date @time 2024/11/19 17:37
     **/
    public boolean exists(String key){
        Jedis jedis = getRedisClient();
        if (jedis != null) {
            try {
                return jedis.exists(key);
            } finally {
                jedis.close();
            }
        }
        return false;
    }
    

    /**
     * @description 加分不是锁，防止连续点击
     * @author cwj
     * @param [lockKey, expireTime]
     * @return boolean
     * @date @time 2025/3/22 17:57
     **/
    public boolean tryLock(String lockKey, int expireTime) {
        try (Jedis jedis = jedisPool.getResource()) {
            // 使用 SETNX 设置分布式锁，锁过期时间使用 EXPIRE 设置
            Long result = jedis.setnx(lockKey, "1");
            if (result == 1) {
                // 设置成功后，设置锁的过期时间
                jedis.expire(lockKey, expireTime);
                return true;
            }
            return false;
        }
    }

    /**
     * @description 释放分布式锁
     * @author cwj
     * @param [lockKey]
     * @return void
     * @date @time 2025/3/23 9:12
     **/
    public void releaseLock(String lockKey) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.del(lockKey);
        }
    }

}
